package es.geoorge.hundirlaflota;

import java.util.*;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.AsyncTask;
import android.widget.Toast;

/**
 * Esta es la clase intermediaria que se encarga de recibir ambos tableros y dar acceso a ellos desde un mismo sitio, asi como poder comprobar las coordenadas del jugador y las
 * autogeneradas por la maquina. extiende de asyntask ya que se utiliza para modificar el hilo grafico cuando nos interesa a nsootros segun las reacciones a las coordenadas generadas por el hilo de la ia.
 * @author georthik
 *
 */
public class Mensajero extends AsyncTask<Boolean, Integer, Boolean>{
	Activity act;
	int duracion = Toast.LENGTH_SHORT; 
	mView tableroJugador;
	mView tableroMaquina;
	boolean turnoJugador=true;
	boolean casillaPulsada= false;
	private Context con;
	Maquina maquina;
	private boolean cambio;
	int barcosJugadorHundidos;	
	SoundManager sound;
	Intent intMostrarEstadisticas;
	static int disparo,agua,tocado;	

	/**
	 * Recibe la actividad actual para poder modificar el hilo grafico, llamar otras actividades o finalizar esta una vez se termina el juego.
	 * @param actividad
	 */
	public Mensajero (Activity actividad) {
		act=actividad;
		con = act.getApplicationContext();
		int turno=(int)(Math.random()*4);
		if(turno%2==0){
			turnoJugador=!turnoJugador;
		}
		sound = new SoundManager(con);
		act.setVolumeControlStream(AudioManager.STREAM_MUSIC);
        disparo = sound.load(R.raw.disparo);
        agua = sound.load(R.raw.agua);
        tocado = sound.load(R.raw.tocado);
	}
	
	@Override
	protected Boolean doInBackground(Boolean... params) {
		do{
		}while(!tableroJugador.finJuego());
		return true;
	}
	
	/**
	 * desde aqui se realizan los cambios sobre el hilo grafico.
	 */
    protected void onProgressUpdate(Integer... progress) {
    	int n = progress[0].intValue();
    	Toast toast=null;
    	switch(n){
	    	case 1:;break;
			case 2:tableroJugador.invalidate();break;
			case 3:;break;
			case 4:;break;
	    	case 5:;break;
			case 6:;break;
    		case 7:;break;
	    	case 8:
	    		toast = Toast.makeText(con, "la maquina ha ganado", duracion);
		    	toast.show();
		    	
		    	try {
					Thread.sleep(1400);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
		    	intMostrarEstadisticas = new Intent (act, Estadisticas.class);
		    	act.startActivity(intMostrarEstadisticas);
		    	act.finish();
	    	break;
	    	case 9:
	    		toast = Toast.makeText(con, "El jugador ha ganado", duracion);
		    	toast.show();
			try {
				Thread.sleep(1400);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			intMostrarEstadisticas = new Intent (act, Estadisticas.class);
			act.startActivity(intMostrarEstadisticas);
				act.finish();
    		break;
    	}
    }

    protected void onPostExecute(Boolean result) {
        if(result){
        	publishProgress(7);
        }
    }
	

    /**
     * Este es el metdo que sirve para recibir el tablero generado por la maquina una vez esta completo.
     * @param t tablero de la maquina
     */
	public void enviarTabMaquina(mView t){
		tableroMaquina=t;
	}

	/**
     * Este es el metdo que sirve para recibir el tablero generado por el jugador una vez esta completo.
     * @param t tablero del jugador
     */
	public void enviarTabJugador(mView t){
		tableroJugador=t;
	}
	
	/**
	 * Recibe el hilo de la ia
	 * @param t
	 */
	public void enviarMaquina(Maquina t){
		maquina=t;
	}
  
	
	/**
	 * metodo llamado cuando la maquina hunde todos los barcos del jugador.
	 */
    public void ganaLaMaquina(){
    	publishProgress(8);
    }
	
    /**
	 * metodo llamado cuando el jugador destruye todos los barcos de la maquina.
	 */
	public void ganaElJugador(){
		publishProgress(9);
	}
	
	/**
	 * Este es el metodo que se encarga de cambiar el turno del jugador al turno de la maquina, tambien refresca la pantalla para ver las modificaciones realizadas
	 */
	public synchronized void jugadorOnAgua(){
		publishProgress(2);
		try{
			Thread.sleep(1000);
		}catch(Exception e){}
		turnoJugador=false;
		publishProgress(2);
		notify();	
	}
	
	/**
	 * Metodo de generacion de coordenadas aleatorias por parte de la maquina. Estas coordenadas aleatorias pertenecen a un array de la clase Maquina que acorta las posibilidades y las limita al tablero. tambien evita repeticion de turnos
	 */
	public synchronized void generarCoor(){
		sound.play(disparo);
		int n=(int)(Math.random()*maquina.max);
		StringTokenizer str=new StringTokenizer(maquina.arrCoordenadas[n],",");
		int x=Integer.parseInt(str.nextToken());
		int y=Integer.parseInt(str.nextToken());
		maquina.arrCoordenadas=maquina.nuevoArray(maquina.arrCoordenadas,n);
		switch(tableroJugador.probarCoor(x,y)){
			case 0:
				cambio=true;
				if(tableroJugador.matCasillas[x][y].isDestapado()){
					cambio=false;
				}else{
					tableroJugador.matCasillas[x][y].destapar();
					tableroJugador.matCasillas[x][y].setAgua(true);
					sound.play(agua);
					try {						
						publishProgress(2);
						Thread.sleep(1500);
						if(cambio){
							turnoJugador=true;
						}
						publishProgress(2);
						wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				break;
			case 1:
				maquina.ponAgua(x,y);
				tableroJugador.matCasillas[x][y].destapar();
				tableroJugador.matCasillas[x][y].setAgua(false);
				sound.play(tocado);
				int barcoTocado=(tableroJugador.matriz[x][y])-1;
				tocadoBarco(barcoTocado, x, y);
				break;
		}	
	}
	
	/**
	 * Este metodo es llamado por el de generacion de coordenadas aletorias correspondientes al array de la clase Maquina, cuando se llama a este emtodos es proque la maquina ha tocado un barco del jugador y debe
	 * generar coordenadas adyacentes a este punto hasta conseguir hundir el barco enemigo.
	 * @param barco el barco que ha sido tocado.
	 * @param x coordenada x del punto inicial donde se ha tocado un barco enemigo.
	 * @param y coordenada y del punto inicial donde se ha tocado un barco enemigo.
	 */	
	public synchronized void tocadoBarco(int barco, int x, int y){
		int dir=(int)(Math.random()*4+1);
		boolean direccion=dir%2==0;
		final int xIni=x;
		final int yIni=y;
		int numVertical=(int)(Math.random()*4+1);
		boolean bVertical=numVertical%2==0;
		int numHorizontal=(int)(Math.random()*4+1);
		boolean bHorizontal=numHorizontal%2==0;
		int posicion=-1;
		do{
			sound.play(disparo);
			if(direccion){
				if(bVertical){
					x++;
				}else{
					x--;
				}
				if(tableroJugador.arrBarcos[barco].comprobarCoor(x,y)){
					//tocado
					sound.play(tocado);
					publishProgress(2);
					tableroJugador.matCasillas[x][y].destapar();
					tableroJugador.matCasillas[x][y].setAgua(false);
					try {
						Thread.sleep(500);
					} catch (Exception e) {
						e.printStackTrace();
					}
					maquina.ponAgua(x,y);
					posicion=maquina.buscarCoor(x,y);
					if(posicion!=-1){
						maquina.arrCoordenadas=maquina.nuevoArray(maquina.arrCoordenadas,posicion);
					}
					direccion=!direccion;
				}else{
					//agua
					try {
						cambio=true;
						if(tableroJugador.matCasillas[x][y].isDestapado()){
							cambio=false;
						}else{
							sound.play(agua);
							tableroJugador.matCasillas[x][y].destapar();
							tableroJugador.matCasillas[x][y].setAgua(true);
							try {
								publishProgress(2);
								Thread.sleep(1500);
								
								if(cambio){
									turnoJugador=true;
								}
								publishProgress(2);
								wait();
							} catch (Exception e) {
								e.printStackTrace();
							}
						}	
					} catch (Exception e) {
						e.printStackTrace();
					}
					bVertical=!bVertical;
					x=xIni;
				}
			}else{
				if(bHorizontal){
					y++;
				}else{
					y--;
				}	
				if(tableroJugador.arrBarcos[barco].comprobarCoor(x,y)){
					//tocado
					sound.play(tocado);
					publishProgress(2);
					tableroJugador.matCasillas[x][y].destapar();
					tableroJugador.matCasillas[x][y].setAgua(false);
					direccion=!direccion;
					try {
						Thread.sleep(500);
					} catch (Exception e) {
						e.printStackTrace();
					}
					maquina.ponAgua(x,y);
					posicion=maquina.buscarCoor(x,y);
					if(posicion!=-1){
						maquina.arrCoordenadas=maquina.nuevoArray(maquina.arrCoordenadas,posicion);
					}
				}else{
					//agua
					try {
						cambio=true;
						if(tableroJugador.matCasillas[x][y].isDestapado()){
							cambio=false;
						}else{
							sound.play(agua);
							tableroJugador.matCasillas[x][y].destapar();
							tableroJugador.matCasillas[x][y].setAgua(true);
							try {
								publishProgress(2);
								Thread.sleep(1500);
								
								if(cambio){
									turnoJugador=true;
								}
								publishProgress(2);
								wait();
							} catch (Exception e) {
								e.printStackTrace();
							}
						}	
					} catch (Exception e) {
						e.printStackTrace();
					}
					bHorizontal=!bHorizontal;
					y=yIni;
				}
			}				
			direccion=!direccion;
		}while(!tableroJugador.arrBarcos[barco].estaHundido());
		barcosJugadorHundidos++;
	}	
}